package cn.iocoder.an.module.business.service.repairtask;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.module.business.controller.admin.repairrequest.vo.RepairRequestPageReqVO;
import cn.iocoder.an.module.business.controller.admin.repairrequest.vo.RepairRequestRespVO;
import cn.iocoder.an.module.business.controller.admin.repairrequest.vo.UpdateRepairRequestStatusReqVO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.dal.dataobject.repairrequest.RepairRequestDO;
import cn.iocoder.an.module.business.dal.mysql.repairrequest.RepairRequestMapper;
import cn.iocoder.an.module.business.service.equipmentmanage.EquipmentManageService;
import cn.iocoder.an.module.business.service.repairrequest.RepairRequestService;
import cn.iocoder.an.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.an.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.an.module.business.controller.admin.repairtask.vo.*;
import cn.iocoder.an.module.business.dal.dataobject.repairtask.RepairTaskDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.business.dal.mysql.repairtask.RepairTaskMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.business.enums.ErrorCodeConstants.*;

/**
 * 维修任务 Service 实现类
 *
 * @author zzy
 */
@Service
@Validated
public class RepairTaskServiceImpl implements RepairTaskService {

    @Resource
    private RepairTaskMapper repairTaskMapper;

    @Resource
    private RepairRequestMapper repairRequestMapper;

    @Resource
    private AdminUserService userService;

    @Resource
    private EquipmentManageService equipmentManageService;


    @Override
    public Long createRepairTask(RepairTaskSaveReqVO createReqVO) {
        // 插入
        RepairTaskDO repairTask = BeanUtils.toBean(createReqVO, RepairTaskDO.class);
        repairTaskMapper.insert(repairTask);

        // 返回
        return repairTask.getId();
    }

    @Override
    public void updateRepairTask(RepairTaskSaveReqVO updateReqVO) {
        // 校验存在
        validateRepairTaskExists(updateReqVO.getId());
        // 更新
        RepairTaskDO updateObj = BeanUtils.toBean(updateReqVO, RepairTaskDO.class);
        repairTaskMapper.updateById(updateObj);
        //更新申请单的是否解决和状态
        RepairRequestDO repairRequestDO = repairRequestMapper.selectById(updateReqVO.getRepairId());
        repairRequestDO.setResolved(updateObj.getResolved() != null ? updateObj.getResolved() : 1);
        if (updateReqVO.getStatus() != null) {
            repairRequestDO.setStatus(updateReqVO.getStatus());
        }
        repairRequestMapper.updateById(repairRequestDO);

    }

    @Override
    public void deleteRepairTask(Long id) {
        // 校验存在
        validateRepairTaskExists(id);
        // 删除
        repairTaskMapper.deleteById(id);
    }

    @Override
    public void deleteRepairTaskListByIds(List<Long> ids) {
        // 删除
        repairTaskMapper.deleteByIds(ids);
    }


    private void validateRepairTaskExists(Long id) {
        if (repairTaskMapper.selectById(id) == null) {
            throw exception(REPAIR_TASK_NOT_EXISTS);
        }
    }

    @Override
    public RepairTaskDO getRepairTask(Long id) {
        RepairTaskDO repairTaskDO = repairTaskMapper.selectById(id);
        calculateRepairTime(repairTaskDO);
        return repairTaskDO;
    }

    @Override
    public RepairTaskDO getRepairTaskByRepairId(Long repairId) {
        LambdaQueryWrapper<RepairTaskDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RepairTaskDO::getRepairId, repairId);
        //查询维修任务单信息
        RepairTaskDO repairTaskDO = repairTaskMapper.selectFirstOne(RepairTaskDO::getRepairId, repairId);
        calculateRepairTime(repairTaskDO);
        return repairTaskDO;
    }

    @Override
    public PageResult<RepairTaskDO> getRepairTaskPage(RepairTaskPageReqVO pageReqVO) {
        PageResult<RepairTaskDO> repairTaskDOPageResult = repairTaskMapper.selectPage(pageReqVO);
        repairTaskDOPageResult.getList().forEach(repairTaskDO -> {
            calculateRepairTime(repairTaskDO);
        });
        return repairTaskDOPageResult;
    }


    @Override
    public void updateRepairRequestAndInertTask(UpdateRepairRequestStatusReqVO updateReqVO) {
        // 校验存在
        RepairRequestDO repairRequestDO = repairRequestMapper.selectById(updateReqVO.getId());
        if (repairRequestDO == null) {
            throw exception(REPAIR_REQUEST_NOT_EXISTS);
        } else {
            //更新状态
            repairRequestDO.setStatus(updateReqVO.getStatus());
            if (updateReqVO.getStatus() == 2) {
                //如果点击的是接收按钮 需要生成一条维修任务单
                RepairTaskSaveReqVO taskSaveReqVO = new RepairTaskSaveReqVO();
                //设置维修申请单ID
                taskSaveReqVO.setRepairId(repairRequestDO.getId());
                //设置设备ID 从repairRequestDO中获取
                taskSaveReqVO.setEquipmentId(repairRequestDO.getEquipmentId());
                //生成维修单
                RepairTaskDO repairTask = BeanUtils.toBean(taskSaveReqVO, RepairTaskDO.class);
                repairTaskMapper.insert(repairTask);
            } else if (updateReqVO.getStatus() == 3) {
                //点击的是开始按钮 更新一下任务单的开始时间为当前时间
                LambdaQueryWrapper<RepairTaskDO> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(RepairTaskDO::getRepairId, repairRequestDO.getId());
                RepairTaskDO updateDO = repairTaskMapper.selectFirstOne(RepairTaskDO::getRepairId, updateReqVO.getId());
                updateDO.setStartTime(LocalDateTime.now());
                //设置一下更新时间
                updateDO.setUpdateTime(LocalDateTime.now());
                repairTaskMapper.updateById(updateDO);
            }
        }
        //更新维修申请单状态
        repairRequestMapper.updateById(repairRequestDO);
    }


    @Override
    public PageResult<RepairRequestRespVO> getRepairStatistics(RepairRequestPageReqVO pageReqVO) {
        //1.查询所有符合条件的
        PageResult<RepairRequestDO> pageResult = repairRequestMapper.selectLatestByEquipmentId(pageReqVO);
        PageResult<RepairRequestRespVO> requestRespVOPage = BeanUtils.toBean(pageResult, RepairRequestRespVO.class);
        //2.循环查询每一个设备的所有维修任务单并统计
        requestRespVOPage.getList().forEach(respVO -> {
            EquipmentManageDO equipmentManage = equipmentManageService.getEquipmentManage(respVO.getEquipmentId());
//            respVO.setEquipmentName(equipmentManage.getEquipmentName());
//            respVO.setEquipmentModel(equipmentManage.getEquipmentModel());

            LambdaQueryWrapperX<RepairTaskDO> queryWrapper = new LambdaQueryWrapperX<>();
            queryWrapper.orderByDesc(RepairTaskDO::getUpdateTime);//按照更新时间降序
            Long equipmentId = respVO.getEquipmentId();
            queryWrapper.eq(RepairTaskDO::getEquipmentId, equipmentId);
            List<RepairTaskDO> taskDOList = repairTaskMapper.selectList(queryWrapper);
            //设置维修次数
            respVO.setRepairCount(taskDOList.size());

            //3.取最新一条 点击单号的时候显示最新的一条维修任务
            if (!taskDOList.isEmpty()) {
                RepairTaskDO latestTaskDO = taskDOList.getFirst();
                calculateRepairTime(latestTaskDO);
                RepairTaskRespVO latest = BeanUtils.toBean(latestTaskDO, RepairTaskRespVO.class);
                respVO.setTaskRespVO(latest);
            }

            //4.设置维修历史记录
            List<RepairTaskRespVO> TaskRespVOList = BeanUtils.toBean(taskDOList, RepairTaskRespVO.class);
//            respVO.setTaskRespVOList(TaskRespVOList);

            //5.统计维修时长和维修成本
            //总的有多少分钟
            Integer totalMin = 0;
            //总的时长 转换成小时
            Double totalHours = 0.0;
            //维修成本
            BigDecimal totalCost = BigDecimal.ZERO;

            for (RepairTaskDO taskDO : taskDOList) {
                calculateRepairTime(taskDO);//计算的是分钟
                Integer repairDuration = taskDO.getRepairDuration();
                totalMin += repairDuration;
                totalCost = totalCost.add(taskDO.getRepairCost() != null ? taskDO.getRepairCost() : BigDecimal.ZERO);
            }
            // 将总分钟转换为小时（保留 2 位小数，四舍五入）
            // 将总分钟转换为小时，并保留 2 位小数（四舍五入）
            totalHours = Math.round((totalMin / 60.0) * 100.0) / 100.0;
            respVO.setRepairHours(totalHours);
            respVO.setTotalCost(totalCost);

        });
        return requestRespVOPage;
    }


    //计算维修时长 分钟
    public void calculateRepairTime(RepairTaskDO repairTaskDO) {
        if (repairTaskDO == null) {
            return;
        }

        LocalDateTime startTime = repairTaskDO.getStartTime();
        LocalDateTime endTime = repairTaskDO.getEndTime();

        if (startTime != null) {
            // 如果结束时间为空，默认为当前时间
            if (endTime == null) {
                endTime = LocalDateTime.now();
            }

            // 使用 ChronoUnit 计算两个 LocalDateTime 之间的分钟数
            long durationInMinutes = ChronoUnit.MINUTES.between(startTime, endTime);

            // 如果业务要求不能为负（比如开始时间在结束时间之后），可以加判断
            if (durationInMinutes < 0) {
                durationInMinutes = 0; // 或抛异常，视业务而定
            }

            repairTaskDO.setRepairDuration((int) durationInMinutes);
        } else {
            // 没有开始时间，无法计算，设为 0 或 null（根据数据库字段是否允许）
            repairTaskDO.setRepairDuration(0);
        }


    }


}